package controllers;

import java.util.*;

import play.mvc.*;
import play.data.*;
import static play.data.Form.*;
import play.*;

import views.html.*;
import views.html.passerQCM.*;

import models.*;

/**
 * @author jubonnea
 *
 */
public class PasserQCM extends Controller {
	

	/**
	 * la fonction permet de lister l'ensemble des QCM
	 * @return une vue prenant en paramètre tous les Qcm présents en BD
	 */
	public static Result listeQCM() {
		Qcm q = new Qcm();
		return ok(listeQcm.render(Qcm.findAll(), q, ""));
	}

	public static Result authentificationQcm(){
		
		DynamicForm dynamicForm = form().bindFromRequest();
		Qcm q = Qcm.findById(Long.parseLong(dynamicForm.get("idQcm")));
		String cle = dynamicForm.get("cleQcm");
		
		System.out.println("id QCM  : " + dynamicForm.get("idQcm"));

		System.out.println("cle : " + dynamicForm.get("cleQcm"));

		System.out.println(q.getCleAuthentification().equals(cle));
		if(q.getCleAuthentification().equals(cle) == true){
			return ok(debQcm.render(q));	
		}	
		else{
			return ok(listeQcm.render(Qcm.findAll(), q, "La cle saisie est incorrecte veuillez réessayer"));

			
		}	
	}

	/**
	 * la fonction prend en paramètre un id et récupère le QCM correspondant à cet ID
	 * elle va permettre de commencer à passer un Qcm.
	 * @return une vue prenant en paramètre le Qcm correspondant à l'id
	 */
	public static Result debutQCM(Long id) {

		Qcm QcmDetails = Qcm.findById(id);
		return ok(debQcm.render(QcmDetails));

	}

	/**
	 * la fonction prend en paramètre un id et récupère l'UserQcm correspondant à cet ID
	 * elle va permettre d'initaliser l'UserQcm a partir de l'id de l'étudiant en session et le QCM sélectionné
	 * @return la question suivante
	 */
	public static Result initialisationUserQcm(Long id) {

		Qcm qcmRep = Qcm.findById(id);

		UserQcm userQcm = new UserQcm();
		
		User us = User.findById(Long.parseLong(session("id")));
		userQcm.setUser(us);
		userQcm.setQcm(qcmRep);
		userQcm.save();

		return questionSuivanteQCM(userQcm.getIdUserQcm());

	}
	

	/**
	 * la fonction prend en paramètre un id et récupère l'UserQcm correspondant à cet ID
	 * elle va permettre d'afficher la question suivante tant qu'il y a des questions restantes
	 * @return la question suivante ou si c'est la fin la fct calcule la note
	 */
	public static Result questionSuivanteQCM(Long id) {
		double total = 0.0;

		UserQcm userQcm = UserQcm.findById(id);

		DynamicForm dynamicForm = form().bindFromRequest();
		int numQ = Integer.parseInt(dynamicForm.get("numQ"));

		Question q = userQcm.getQcm().getListeQuestions().get(numQ);
		Choix choix, choixUser;

		Iterator<Choix> itc = q.getListeChoix().iterator();
		while (itc.hasNext()) {
			choix = (Choix) itc.next();
			if (dynamicForm.get("Choix" + choix.getIdChoix()) != null) {
				choixUser = Choix.findById(Long.parseLong(dynamicForm
						.get("Choix" + choix.getIdChoix())));
				if (choixUser != null) {
					userQcm.getListeChoixUser().add(choixUser);
					System.out
							.println("ajout ok : " + userQcm.toString() + "\n");
				}
			}
		}
		//on sauvegarde dans la base de données
		userQcm.save();

		if (numQ < userQcm.getQcm().getListeQuestions().size() - 1) {
			numQ++;
			return ok(questionQcm.render(numQ, userQcm));
		}

		else {
			return calculNote(id);
		}
	}
	

	/**
	 * la fonction prend en paramètre un id de l'étudiant et l'id du Qcm
	 * elle affiche :
	 * 1 si la question répondue par l'étudiant est bonne, 
	 * -1 si la question répondue est fausse et 
	 * 0 si l'étudiant n'a pas répondu à la question.
	 * @return une Map contenant pour chaque question du Qcm la valeur 1, -1 ou 0
	 */
	public static Map<Question, Double> correction(Long idUser, Long idQcm) {
		Map<Question, Double> repUser = new HashMap<Question, Double>();
		UserQcm userQcm = UserQcm.findByIds(idQcm, idUser);
		Question question;
		Choix choix;
		int cpt_repUser;
		int cpt_repJuste;

		Iterator<Question> itq = userQcm.getQcm().getListeQuestions()
				.iterator();
		while (itq.hasNext()) {
			question = itq.next();
			Iterator<Choix> itc = question.getListeChoix().iterator();
			cpt_repUser = 0;
			cpt_repJuste = 0;
			while (itc.hasNext()) {
				choix = itc.next();
				if (choix.getEstVrai()) {
					cpt_repJuste++;
					if (userQcm.getListeChoixUser().contains(choix)) {
						cpt_repUser++;
					}
				} else {
					if (userQcm.getListeChoixUser().contains(choix)) {
						cpt_repUser = -1;
						repUser.put(question, -1.0);
						break;
					}
				}
			}
			if (cpt_repUser != -1) {
				if (cpt_repUser == 0)
					repUser.put(question, 0.00);
				else if (cpt_repUser == cpt_repJuste)
					repUser.put(question, 1.00);
				else if (cpt_repUser != cpt_repJuste)
					repUser.put(question, -1.00);
			}
		}
		return repUser;
	}
	


	/**
	 * la fonction prend en paramètre un id et récupère l'UserQcm correspondant à cet ID
	 * elle va permettre de calculer la note de l'étudiant pour un Qcm à partir de la map revoyée par la fonction correction
	 * @return la question l'étudiant Qcm et la Map correction
	 */
	public static Result calculNote(Long id) {
		Double noteFinale =0.0;
		Double total = 0.0;
		UserQcm userQcm = UserQcm.findById(id);
		Map<Question, Double> correct = correction(userQcm.getUser().getIdUser(), userQcm.getQcm().getIdQcm());
		
		for(Question question : userQcm.getQcm().getListeQuestions()){
			total += userQcm.getQcm().findQcmNiveauQuestion(question.getNiveauQuestion()).getPointPositif();
			
			//si la reponse à la question est bonne 
			if(correct.get(question)==1){
				//on ajoute les points positifs correspondant à la question
				noteFinale += userQcm.getQcm().findQcmNiveauQuestion(question.getNiveauQuestion()).getPointPositif();
			}

			//si la reponse à la question est fausse 
			else if(correct.get(question)==-1){
				//on reture les points negatifs correspondant à la question
				noteFinale -= userQcm.getQcm().findQcmNiveauQuestion(question.getNiveauQuestion()).getPointNegatif();	
			}	
		}
		
		//si la note est négative on la ramène à 0
		if (noteFinale < 0){
			noteFinale = 0.0;
		}
		
		//ramène la note finale sur 20 
		userQcm.setNote((noteFinale*20)/total);
		
		userQcm.save();
		
		return ok(finQcm.render(userQcm, correct)); 
	}
	
	public static Result accederQcm(Long id) {
		
		Qcm qcmRep = Qcm.findById(id);
		User us = User.findById(Long.parseLong(session("id")));
		
		if(UserQcm.findByIds(qcmRep.getIdQcm(),us.getIdUser()) != null){
			UserQcm userQcm = UserQcm.findByIds(qcmRep.getIdQcm(), us.getIdUser());
			return initialisationUserQcm(userQcm.getIdUserQcm());
			
		} else 
			return TODO;

//		si etud_QCm n'existe pas 
//		appeler initialisation
//		sinon
//		appeler question suivante numQ == nb de rep pour aller directement dans le else.
		
	}
	
	public static Result listeMesQCM(){
		User us = User.findById(Long.parseLong(session("id")));
		List<Qcm> listeQcm = new ArrayList<Qcm>();
		
		if(!us.getListeQcmPasses().isEmpty()){
			for(UserQcm userQcm :us.getListeQcmPasses()){
				listeQcm.add(userQcm.getQcm());
			}
		}
		return ok(listeMesQcm.render(listeQcm));
	}
	
	public static Result correctionQcm(Long id){
		Qcm qcmRep = Qcm.findById(id);
		User us = User.findById(Long.parseLong(session("id")));
		
		System.out.println(qcmRep.getIdQcm());
		System.out.println(us.getIdUser());
		UserQcm userQcm = UserQcm.findByIds(qcmRep.getIdQcm(), us.getIdUser());
		return calculNote(userQcm.getIdUserQcm());		
	}
	
}